#include "JsonRpcNotification.h"
#include <QJsonObject>
#include <QJsonArray>

JsonRpcNotification::JsonRpcNotification()
    : JsonRpcNotification("", QJsonObject())
{
}

JsonRpcNotification::JsonRpcNotification(const QString& method)
    : JsonRpcNotification(method, QJsonObject())
{
}

JsonRpcNotification::JsonRpcNotification(const QString& method, const QJsonObject& params)
    : mMethod(method)
    , mParams(params)
{
}

JsonRpcNotification::~JsonRpcNotification()
{
}

QString JsonRpcNotification::method() const
{
    return mMethod;
}

void JsonRpcNotification::setMethod(const QString& method)
{
    mMethod = method;
}

QJsonObject JsonRpcNotification::params() const
{
    return mParams;
}

void JsonRpcNotification::setParams(const QJsonObject& params)
{
    mParams = params;
}

bool JsonRpcNotification::hasParams() const
{
    return !mParams.isEmpty();
}

QJsonObject JsonRpcNotification::toJson() const
{
    QJsonObject json;
    json["jsonrpc"] = "2.0";
    json["method"] = mMethod;
    
    if (hasParams()) {
        json["params"] = mParams;
    }
    
    return json;
}

JsonRpcNotification JsonRpcNotification::fromJson(const QJsonObject& json, bool* ok)
{
    JsonRpcNotification notification;
    
    if (ok) {
        *ok = true;
    }
    
    // Check if jsonrpc field exists and is "2.0"
    if (!json.contains("jsonrpc") || json["jsonrpc"].toString() != "2.0") {
        if (ok) {
            *ok = false;
        }
        return notification;
    }
    
    // Check if method field exists and is string
    if (!json.contains("method") || !json["method"].isString()) {
        if (ok) {
            *ok = false;
        }
        return notification;
    }
    
    notification.setMethod(json["method"].toString());
    
    // Handle optional params field
    if (json.contains("params")) {
        if (json["params"].isObject()) {
            notification.setParams(json["params"].toObject());
        } else {
            // Invalid params type
            if (ok) {
                *ok = false;
            }
            return notification;
        }
    }
    
    // Notification should not have id field
    if (json.contains("id")) {
        if (ok) {
            *ok = false;
        }
        return notification;
    }
    
    return notification;
}

bool JsonRpcNotification::isValid() const
{
    // Notification must have method and jsonrpc version
    if (mMethod.isEmpty()) {
        return false;
    }
    
    // Notification should not have id
    if (hasId()) {
        return false;
    }
    
    return true;
}